package com.neborosoft.lib.collections.list;

import com.neborosoft.lib.API_8.Collections;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;

/**
 * Project: FlyingDog
 * User: stikhonenko
 * Date: 12/10/12
 * Time: 3:30 PM
 */
public class SortedList<T> extends ArrayList<T> {
    private Comparator<T> comparator;

    private void setDefaultComparator(){
        comparator = new Comparator<T>() {
            @Override
            public int compare(T a, T b) {
                return ((Comparable<T>)a).compareTo(b);
            }
        };
    }

    private void sort(){
        Collections.sort(this, comparator);
    }

    public Comparator<T> getComparator() {
        return comparator;
    }

    public final void setComparator(Comparator<T> comparator) {
        this.comparator = comparator;
        onSetComparator();
    }

    protected void onSetComparator() {
        sort();
    }

    public SortedList(int capacity, Comparator<T> comparator) {
        super(capacity);
        this.comparator = comparator;
    }

    public SortedList(Comparator<T> comparator) {
        this.comparator = comparator;
    }

    public SortedList(Collection<? extends T> collection, Comparator<T> comparator) {
        this.comparator = comparator;
        addAll(collection);
    }

    public SortedList(){
        setDefaultComparator();
    }

    public SortedList(int capacity) {
        super(capacity);
        setDefaultComparator();
    }

    public SortedList(Collection<? extends T> collection) {
        super(collection);
        setDefaultComparator();
        addAll(collection);
    }

    protected void arrayListAdd(int index, T object){
        super.add(index, object);
    }

    @Override
    public boolean add(T object) {
        int index = indexOf(object);
        if(index < 0){
            index = -index - 1;
        }
        arrayListAdd(index, object);
        return true;
    }

    @Override
    public void add(int index, T object) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean addAll(Collection<? extends T> collection) {
        if(collection.isEmpty()){
            return false;
        }

        super.addAll(collection);
        sort();

        return true;
    }

    @Override
    public boolean addAll(int index, Collection<? extends T> collection) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int indexOf(Object object) {
        return Collections.binarySearch(this, (T)object, comparator);
    }

    public void invalidate(){
        sort();
    }

    @Override
    public boolean remove(Object object) {
        int index = indexOf(object);
        if(index >= 0){
            super.remove(index);
            return true;
        }

        return false;
    }

    @Override
    public boolean contains(Object object) {
        return indexOf(object) >= 0;
    }

    @Override
    public boolean containsAll(Collection<?> collection) {
        for(Object object : collection){
            if(!contains(object)){
                return false;
            }
        }

        return true;
    }

    @Override
    public boolean removeAll(Collection<?> collection) {
        boolean listModified = false;

        for(Object object : collection){
            if(remove(object)){
                listModified = true;
            }
        }

        return listModified;
    }
}
